﻿/*
 *  Copyright 2012 HEINER DIRECT GmbH & Co. KG
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * 
 * @Author Rafael Dabrowski
 * 
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Linq;
using System.Runtime.Serialization;

namespace HDI.SharePoint.Webparts.HDITable.HDITable
{

    #region WebPart
    [ToolboxItemAttribute(false)]
    public class HDITableWP : WebPart, IWebEditable
    {
        // Der Pfad wird unter Umständen automatisch aktualisiert, wenn das Visual WebPart-Projektelement geändert wird.
        private const string _ascxPath = @"~/_CONTROLTEMPLATES/HDI.SharePoint.Webparts.HDITable/HDITable/HDITableUserControl.ascx";

        #region Editor Webpart Config

       
        public Config Config { get; set; }
        [Personalizable(true)]
        public String sConfig { get; set; }

        EditorPartCollection IWebEditable.CreateEditorParts()
        {
            var editors = new List<EditorPart>();
            var editorPart = new HDITableWPEditorPart();
            editorPart.ID = ID + "_editorPart";
            editors.Add(editorPart);

            return new EditorPartCollection(editors);
        }

        /// <summary>
        /// Returns parent web part to editor part
        /// </summary>
        object IWebEditable.WebBrowsableObject
        {
            get { return this; }
        }

        #endregion

        #region Old Vars

        //[WebBrowsable(true)]
        //[WebDescription("/ für Root; /Webname für Unterweb")]
        //[WebDisplayName("SharePoint Web")]
        //[Category("Listeneinstellungen")]
        //[Personalizable(PersonalizationScope.Shared)]
        //public string sWeb { get; set; }

        //[WebBrowsable(true)]
        //[WebDescription("Name der Liste")]
        //[WebDisplayName("Listenname")]
        //[Category("Listeneinstellungen")]
        //[Personalizable(PersonalizationScope.Shared)]
        //public string sTable { get; set; }

        //[WebBrowsable(true)]
        //[WebDescription("Name der Liste")]
        //[WebDisplayName("Viewname")]
        //[Category("Listeneinstellungen")]
        //[Personalizable(PersonalizationScope.Shared)]
        //public string sView { get; set; }

        //[WebBrowsable(true)]
        //[WebDescription("Name der Liste")]
        //[WebDisplayName("CAML Query")]
        //[Category("Listeneinstellungen")]
        //[Personalizable(PersonalizationScope.Shared)]
        //public string sQuery { get; set; }

        //[WebBrowsable(true)]
        //[WebDescription("Name der Liste")]
        //[WebDisplayName("Query Parameter")]
        //[Category("Listeneinstellungen")]
        //[Personalizable(PersonalizationScope.Shared)]
        //public string sQueryParam { get; set; }

        //[WebBrowsable(true)]
        //[WebDescription("getrennt durch ;")]
        //[WebDisplayName("Gruppierungsfelder")]
        //[Category("Listeneinstellungen")]
        //[Personalizable(PersonalizationScope.Shared)]
        //public string sGroupFields { get; set; }



        //[WebBrowsable(true)]
        //[WebDescription("Name der Liste|Anzeigename;")]
        //[WebDisplayName("Anzeigenamen")]
        //[Category("Listeneinstellungen")]
        //[Personalizable(PersonalizationScope.Shared)]
        //public string sDisplayFields { get; set; }


        //[WebBrowsable(true)]
        //[WebDescription("Name der Liste|operation[|formatierung]")]
        //[WebDisplayName("Berechnungsfeld Einstellungen")]
        //[Category("Listeneinstellungen")]
        //[Personalizable(PersonalizationScope.Shared)]
        //public string sComputedFields { get; set; }



        //[WebBrowsable(true)]
        //[WebDescription("Name der Liste")]
        //[WebDisplayName("Geschlossen")]
        //[Category("Listeneinstellungen")]
        //[Personalizable(PersonalizationScope.Shared)]
        //public bool sClosed { get; set; }

        #endregion

        SPWeb Web = null;
        SPList List = null;
        HDITableUserControl control = null;

        protected void debug(string text)
        {
            Controls.Add(new LiteralControl(text + "<br>"));
        }

        public string userTitle(string title)
        {
            if (Config.DisplayNames.Count > 0 && Config.DisplayNames.Exists(x => x.name == title))
            {
                return Config.DisplayNames.Find(x => x.name == title).display;
            }
            return title;
        }

        protected override void CreateChildControls()
        {

           
            control = (HDITableUserControl)Page.LoadControl(_ascxPath);
            try
            {

                Config = Helper.Deserialize<Config>(sConfig);

                if (Config == null)
                {
                    throw new Exception("Bitte die Configuration ausführen!");
                }

                string sWeb = "";
                if (String.IsNullOrEmpty(Config.Web.name))
                    sWeb = SPContext.Current.Web.ServerRelativeUrl;
                else
                    sWeb = Config.Web.url.Replace(SPContext.Current.Site.Url, "");

                using (Web = SPContext.Current.Site.AllWebs[sWeb])
                {

                    if (string.IsNullOrEmpty(Config.List.name))
                    {
                        throw new Exception("Bitte eine Liste eintragen.");
                    }

                    List = Web.Lists[Config.List.name];

                    control.Title = List.Title;
                    if (Config.GroupFields.Count == 0)
                    {
                        control.addGroup(" ");
                        Config.GroupFields = new List<ConfigField>();
                    }


                    SPListItemCollection LIC = getItems();

                    if (Config.CalcFields.Count > 0)
                    {
                        foreach (var s in Config.CalcFields)
                        {

                            if (String.IsNullOrEmpty(s.format))
                                control.addGroupValue(userTitle(s.field), s.operation);
                            else
                                control.addGroupValue(userTitle(s.field), s.operation, s.format);
                        }
                    }

                    //Writes Fields
                    foreach (SPField field in LIC.Fields)
                    {
                        if (!Config.GroupFields.Exists(x => x.name.Equals(field.Title)) && getFields().Contains(field.InternalName))
                        {
                            control.CellFields.Add(userTitle(field.Title));
                        }
                    }

                    foreach (SPListItem item in LIC)
                    {

                        Group group = null;

                        //Prepares "group" for adding item
                        if (Config.GroupFields.Count != 0)
                        {
                            foreach (var groupfield in Config.GroupFields)
                            {

                                String Value = item.GetFormattedValue(groupfield.internalName);

                                if (group == null)
                                {
                                    if (control.Groups.Exists(x => x.Title.Equals(Value)))
                                    {
                                        group = control.Groups.Find(x => x.Title.Equals(Value));
                                    }
                                    else
                                    {
                                        group = control.addGroup(Value);
                                        if (Config.Closed)
                                        {
                                            group.closed = true;
                                        }
                                    }
                                }
                                else
                                {
                                    if (group.Groups.Exists(x => x.Title.Equals(Value)))
                                    {
                                        group = group.Groups.Find(x => x.Title.Equals(Value));
                                    }
                                    else
                                    {
                                        group = group.addGroup(Value);
                                        if (Config.Closed)
                                        {
                                            group.closed = true;
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {

                            group = control.Groups[0];

                        }
                        Row row = group.addRow(item.ID);

                        foreach (SPField field in item.Fields)
                        {
                            try
                            {
                                if (getFields().Contains(field.InternalName))
                                {
                                    row.addCell(userTitle(field.Title), item.GetFormattedValue(field.InternalName));
                                }
                            }
                            catch
                            {
                                row.addCell(userTitle(field.Title), "FEHLER");
                            }
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                debug(ex.Message.ToString());
               
            }

            Controls.Add(control);
        }

        private SPListItemCollection getItems()
        {
            try
            {
                SPListItemCollection items = null;
                if (!String.IsNullOrEmpty(Config.Caml) && Config.ViewOption == "CAML")
                {
                    SPQuery query = new SPQuery();
                    List<string> paramList = null;
                    if (!String.IsNullOrEmpty(Config.QueryParam))
                    {
                        paramList = new List<string>();
                        foreach (string param in Config.QueryParam.Split(';'))
                        {
                            paramList.Add(Context.Request[param]);
                        }
                        Config.Caml = String.Format(Config.Caml, paramList.ToArray());
                    }
                    query.Query = Config.Caml.Replace("\n", "");
                    query.ViewFieldsOnly = false;
                    items = this.List.GetItems(query);
                }
                else if (!String.IsNullOrEmpty(Config.View.name) && Config.ViewOption == "View")
                {
                    SPView view = this.List.Views[new Guid(Config.View.id)];
                    items = this.List.GetItems(view);

                }
                else
                {
                    return this.List.Items;
                }
                return items;
            }
            catch (Exception ex)
            {
                throw new Exception("Irgendwas mit der View nicht OK. Orginal: " + ex.Message);
            }

        }
        private List<string> _fields;
        private List<string> getFields()
        {
            if (_fields == null)
            {
                _fields = new List<string>();
                if (Config.ViewOption != "View")
                {
                    foreach (SPField field in getItems().Fields)
                    {
                        _fields.Add(field.Title);
                    }
                }
                else
                {
                    SPView view = this.List.Views[new Guid(Config.View.id)];
                    foreach (string field in view.ViewFields)
                    {
                        _fields.Add(field);
                    }

                }
            }
            return _fields;
        }

    }
    #endregion

    #region Editor Zone

    public class HDITableWPEditorPart : EditorPart
    {

        protected HDITableWP ParentWebPart { get; set; }
        protected TextBox JSON { get; set; }

        public HDITableWPEditorPart()
        {
            Title = "Konfiguration";
        }


        protected override void CreateChildControls()
        {
            JSON = new TextBox();
            JSON.CssClass = "JSON";

            ReferencePrevalidatedScript("$.colorbox", "/_layouts/HDI.SharePoint.Webparts.HDICharts2/js/colorbox.js");
            Controls.Add(new LiteralControl("<script type='text/javascript'>$(function(){$('.colorbox').colorbox();});</script>"));
            Controls.Add(new LiteralControl("<a href='/_layouts/HDI.SharePoint.Webparts.HDITable/ConfigForm.htm?" + DateTime.Now.ToFileTime() + "' title='HDITable Konfiguration' class='colorbox'>KONFIGURIEREN</a>"));


            ReferencePrevalidatedScript("ko", "/_layouts/HDI.SharePoint.Webparts.HDICharts2/js/knockout.js");
            ReferencePrevalidatedScript("$.qtip", "/_layouts/HDI.SharePoint.Webparts.HDICharts2/js/qtip.js");
            ReferencePrevalidatedScript("CodeMirror", "/_layouts/HDI.SharePoint.Webparts.HDICharts2/js/Codemirror.js");
            ReferencePrevalidatedScript("TableConfig", "/_layouts/HDI.SharePoint.Webparts.HDITable/js/ConfigForm.js?"+DateTime.Now.ToFileTimeUtc());
            
            Controls.Add(JSON);

            base.CreateChildControls();
            ChildControlsCreated = true;
        }

        /// <summary>
        /// Reads current value from parent web part and show that in the ddl
        /// </summary>
        public override void SyncChanges()
        {
            EnsureChildControls();
            ParentWebPart = WebPartToEdit as HDITableWP;
            try
            {
                if (ParentWebPart != null && WebPartManager.Personalization.Scope == PersonalizationScope.Shared)
                {
                   
                        JSON.Text = ParentWebPart.sConfig;
                }
            }
            catch
            {
                JSON.Text += "Hmmm";
            }
        }

        /// <summary>
        /// Applies change in editor part ddl to the parent web part
        /// </summary>
        /// <returns></returns>
        public override bool ApplyChanges()
        {
            try
            {
                EnsureChildControls();
                ParentWebPart = WebPartToEdit as HDITableWP;

                if (ParentWebPart != null && WebPartManager.Personalization.Scope == PersonalizationScope.Shared)
                {
                  //  ParentWebPart.Config = Helper.Deserialize<Config>(JSON.Text);
                    ParentWebPart.sConfig = JSON.Text;
                }

                // The operation was succesful
                return true;
            }
            catch
            {
                // Because an error has occurred, the SyncChanges() method won’t be invoked.
                return false;
            }
        }

        private void ReferencePrevalidatedScript(string objectToValidate, string scriptPath)
        {
            Controls.Add(new LiteralControl(string.Format(
                @"<script>if (typeof ({0}) == ""undefined"") {{
                                                                document.write(""<script"" + "" src='{1}'><"" + ""/script>"");
                                                                }}
                                                            </script>",
                objectToValidate, scriptPath)));
        }
    }

    #endregion
}
